package net.cyue.simple.container;

import net.cyue.simple.container.annotation.Injectable;
import net.cyue.simple.container.data.InjectableMetaType;
import net.cyue.simple.container.injector.Injector;
import net.cyue.simple.container.injector.MetaTypeFactory;
import net.cyue.simple.container.util.AnnotationScanner;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class ContainerContext {

    private final InstanceContainer instanceContainer = new InstanceContainer();
    private final Injector injector = new Injector(this.instanceContainer.getInstanceRegistry());
    private final List<String> basePackageList;

    public ContainerContext() {
        this.basePackageList = new ArrayList<>();
        this.init();
    }
    public ContainerContext(String basePackageName) {
        this.basePackageList = Collections.singletonList(basePackageName);
        this.init();
    }
    public ContainerContext(String... basePackageNames) {
        this.basePackageList = Arrays.asList(basePackageNames);
        this.init();
    }
    public ContainerContext(List<String> basePackageList) {
        this.basePackageList = basePackageList;
        this.init();
    }

    private void init() {
        for (String basePackage : basePackageList) {
            this.initPackage(basePackage);
        }
    }

    private void initPackage(String packageName) {
        List<Class<?>> injectableClassList = AnnotationScanner.scan(
            packageName,
            Injectable.class
        );
        System.out.println("找到 Injectable class：" + injectableClassList);
        for (Class<?> clz : injectableClassList) {
            Injectable injectable = clz.getAnnotation(Injectable.class);
            String name = Injector.getInjectableName(injectable);
            InjectableMetaType injectableMetaType = MetaTypeFactory.createInjectableMetaType(clz, name);
            this.instanceContainer.addInjectable(injectableMetaType);
        }
    }

    public Injector getInjector() {
        return this.injector;
    }
    public void doInject(Object obj) {
        this.injector.doInject(obj);
    }
}
